package com.thiswhyme.republish.rabbitmq.config;

import com.thiswhyme.republish.common.UidGenService;
import com.thiswhyme.republish.rabbitmq.core.*;
import com.thiswhyme.republish.rabbitmq.datasource.HistoryMessageInfoRepo;
import com.thiswhyme.republish.rabbitmq.datasource.MessageInfoRepo;
import com.thiswhyme.republish.rabbitmq.datasource.MessageInfoSqlBuilder;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.config.GlobalChannelInterceptor;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.sql.DataSource;

/**
 * rabbitmq消息发送重试配置
 * Created by thiswhyme on 2021-03-21.
 */
@Import({ExecutorConfig.class})
@EnableConfigurationProperties(BindingServicePlusProperties.class)
@EnableScheduling
public class RabbitmqPublishRetryConfig {

    @Bean
    @ConditionalOnMissingBean(MessageInfoSqlBuilder.class)
    public MessageInfoSqlBuilder messageInfoSqlBuilder(BindingServicePlusProperties properties) {
        return new MessageInfoSqlBuilder(properties.getMessageTableName());
    }

    @Bean
    @ConditionalOnMissingBean(MessageInfoRepo.class)
    public MessageInfoRepo messageInfoRepo(DataSource dataSource, MessageInfoSqlBuilder messageInfoSqlBuilder) {
        return new MessageInfoRepo(dataSource, messageInfoSqlBuilder);
    }

    @Bean
    @ConditionalOnMissingBean(MessageInfoService.class)
    public MessageInfoService messageInfoService(MessageInfoRepo messageInfoRepo, UidGenService uidGenService) {
        return new MessageInfoService(messageInfoRepo, uidGenService);
    }

    @Bean
    @ConditionalOnMissingBean(RepublishRedisOperation.class)
    public RepublishRedisOperation republishRedisOperation(RedisTemplate redisTemplate) {
        return new RepublishRedisOperation(redisTemplate);
    }

    @Bean("bizMessageChannelInterceptor")
    @ConditionalOnMissingBean(name = "bizMessageChannelInterceptor")
    @GlobalChannelInterceptor
    public RepublishChannelInterceptor bizMessageChannelInterceptor(CompositeMessageConverter compositeMessageConverter,
                                                                    RepublishRedisOperation republishRedisOperation,
                                                                    MessageInfoService messageInfoService,
                                                                    BindingServicePlusProperties bindingServicePlusProperties,
                                                                    UidGenService uidGenService) {
        return new RepublishChannelInterceptor(compositeMessageConverter, republishRedisOperation, messageInfoService,
                bindingServicePlusProperties, uidGenService);
    }

    @Bean
    @ConditionalOnMissingBean(RepublishRunner.class)
    public RepublishRunner republishRunner(@Qualifier("republishDefaultExecutor") ThreadPoolTaskExecutor republishExecutor,
                                           MessageInfoService messageInfoService,
                                           RepublishRedisOperation republishRedisOperation,
                                           BindingServicePlusProperties bindingServicePlusProperties,
                                           ConnectionFactory connectionFactory) {
        return new RepublishRunner(republishExecutor, messageInfoService, republishRedisOperation,
                bindingServicePlusProperties, connectionFactory);
    }

    @Bean
    @ConditionalOnMissingBean(HistoryMessageInfoRepo.class)
    @ConditionalOnProperty(name = "spring.cloud.stream.enable-sharding", havingValue = "true")
    public HistoryMessageInfoRepo historyMessageInfoRepo(DataSource dataSource, MessageInfoSqlBuilder messageInfoSqlBuilder) {
        return new HistoryMessageInfoRepo(dataSource, messageInfoSqlBuilder);
    }

    @Bean
    @ConditionalOnMissingBean(HistoryMessageInfoService.class)
    @ConditionalOnProperty(name = "spring.cloud.stream.enable-sharding", havingValue = "true")
    public HistoryMessageInfoService historyMessageInfoService(MessageInfoRepo messageInfoRepo,
                                                               HistoryMessageInfoRepo historyMessageInfoRepo,
                                                               RedissonClient redissonClient) {
        return new HistoryMessageInfoService(messageInfoRepo, historyMessageInfoRepo, redissonClient);
    }
}
